package com.haoan.index.utils.wx;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.AuthTypeEnum;
import com.ijpay.core.enums.RequestMethodEnum;
import com.ijpay.core.kit.AesUtil;
import com.ijpay.core.kit.PayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxDomainEnum;
import com.ijpay.wxpay.enums.v3.CertAlgorithmTypeEnum;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.FileWriter;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;

/**
 * @Auther: Kai
 * @Date: 2024/9/10
 * @Description: com.haoan.utils.wx
 */
@Slf4j
public class WxpayCertUtil {
    /**
     * 商户API证书序列号
     */
    static String serialNo;
    /**
     * 平台证书序列号
     */
    static String platSerialNo;

    /**
     * 获取商户API证书序列号
     *
     * @return
     */
    public static String getSerialNumber() {
        if (StrUtil.isEmpty(serialNo)) {
            X509Certificate certificate = PayKit.getCertificate(WxpayConstant.certPath);
            if (null != certificate) {
                serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
                // 提前两天检查证书是否有效
                boolean isValid = PayKit.checkCertificateIsValid(certificate, WxpayConstant.mchId, -2);
                log.info("证书是否可用 {} 证书有效期为 {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN));
            }
//            System.out.println("输出证书信息:\n" + certificate.toString());
//            // 输出关键信息，截取部分并进行标记
//            System.out.println("证书序列号:" + certificate.getSerialNumber().toString(16));
//            System.out.println("版本号:" + certificate.getVersion());
//            System.out.println("签发者：" + certificate.getIssuerDN());
//            System.out.println("有效起始日期：" + certificate.getNotBefore());
//            System.out.println("有效终止日期：" + certificate.getNotAfter());
//            System.out.println("主体名：" + certificate.getSubjectDN());
//            System.out.println("签名算法：" + certificate.getSigAlgName());
//            System.out.println("签名：" + certificate.getSignature().toString());
        }
        System.out.println("serialNo:" + serialNo);
        return serialNo;
    }

    /**
     * 获取平台证书序列号
     *
     * @return
     */
    private static String getPlatSerialNumber() {
        if (StrUtil.isEmpty(platSerialNo)) {
            X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(WxpayConstant.platformCertPath));
            platSerialNo = certificate.getSerialNumber().toString(16).toUpperCase();
        }
        System.out.println("platSerialNo:" + platSerialNo);
        return platSerialNo;
    }

    private static void savePlatformCert(String associatedData, String nonce, String cipherText, String algorithm, String certPath) throws Exception {
        String apiV3Key = WxpayConstant.apiV3Key;
        String publicKey;
        if (StrUtil.equals(algorithm, AuthTypeEnum.SM2.getPlatformCertAlgorithm())) {
            publicKey = PayKit.sm4DecryptToString(apiV3Key, cipherText, nonce, associatedData);
        } else {
            AesUtil aesUtil = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));
            // 平台证书密文解密
            // encrypt_certificate 中的  associated_data nonce  ciphertext
            publicKey = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), cipherText);
        }
        if (StrUtil.isNotEmpty(publicKey)) {
            log.info("publicKey: {}", publicKey);
            // 保存证书
            FileWriter writer = new FileWriter(certPath);
            writer.write(publicKey);
            writer.flush();
            // 获取平台证书序列号
            X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));
            log.info("serialNumber: {}", certificate.getSerialNumber().toString(16).toUpperCase());
        }
    }


    /**
     * 获取平台证书列表
     */
    private static void v3Get() throws Exception {
        IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.GET, WxDomainEnum.CHINA.toString(), CertAlgorithmTypeEnum.getCertSuffixUrl(CertAlgorithmTypeEnum.RSA.getCode()), WxpayConstant.mchId, getSerialNumber(), null, WxpayConstant.keyPath, "", AuthTypeEnum.RSA.getCode());
        Map<String, List<String>> headers = response.getHeaders();
        log.info("请求头: {}", headers);
        String timestamp = response.getHeader("Wechatpay-Timestamp");
        String nonceStr = response.getHeader("Wechatpay-Nonce");
        String serialNumber = response.getHeader("Wechatpay-Serial");
        String signature = response.getHeader("Wechatpay-Signature");
        String body = response.getBody();
        int status = response.getStatus();
        log.info("serialNumber: {}", serialNumber);
        log.info("status: {}", status);
        log.info("body: {}", body);
    }


    public static void main(String[] args) throws Exception {
        //v3Get();
        //保存证书
        String associatedData = "certificate";
        String nonce = "39d56027da63";
        String cipherText = "Re72DS+6gz/uP+TU+EOBZU6t+OLCW12uVO3a9sJflvUJ/ytZL83jaPTsN8vFrTG3VtYnJfyF3pBZVRdsUJd4I98d8sHVbD7AzvNcZSy1hEt/B4uwi6KLnzt7Ctb0c6VsGvvJWRFvyzRJN0WFN5ciUseTwyRapwVfa7NAXGbatAapVEpEx/2jU5qmCy1+tOgyIgN+kLO+alnyJlkfGcLMjLXlQNJ4FQGJMld8kXHHif3i5KrHvRlfZY/TKsJVjLtvhxmCVDmcCQrgUa4P4jSI04Yx1nm7q67AZN7YmZcSb9hka++qes9OTWB+CtG2gsjob36pcWLCMBkrGK8BOhQ2JjM/FtTOGfOjuK/C1SHUz25Ec1xsiypHmRBVyHchjqarTAt9RNsxHIEjpzqL1+xY4l3BzKKa6iDf28BWn4ONmsemcv4PjBFT6KCuuqxAIyjevggK22EJHLKU2G/Povv4TlI4zpzU4AucxqhHEjzoqDXwsutEXVDs6H9uKy1PW7MglcgjMYKjz4DqsXh4R5yMKwQR6z17eUj88DRRGU3uVrtVVlC+ec8Wm6nSGlOQll/IzwuhWdoAM8eL/MFL5mxnvNYuL4h9Bm+U+1GZz65t6a5whIAF6UyAN4Tle8bcHl3uJRH4mYZhlY6jxVj2Kre8XQrURPlz2Ggf+46rW9s6XhU/rwNqUutVonwk1G1Na45CJdPrFaYn0lb7VsspGcxMW0qUyIzf62cgZTGW46mVX96/YZg2ELqwW5iS6ohU73WuI2UAO9lv8AG84xwefEPEANbnXnNiyU9s7Qt+qUE+gv5AXv+Gmg6HWM0evr+yJdb/WoZKH9fiupoqDSUGIAnn+vD2JBFxSIgbvHShjKUhkx7OWbQHZaoQhloHkrT8E4S5S9IgwhmWjBV+I4mP/1GrtQ8T9rtA9qwl3C+n7tMOc1jHI2I+z4/VZlmUz4YtGBL8qOl+6AWHBA0nU8UnsNkGs9KB3A5CqRgnaZOykI3HeEjTKSChE1AQMOwdIWxNoaERGfu3+H9OZS6oSLX/3mCQmFKm0g9YVzFi8OvZcymX8kVMndnNkfFThr4MF3TZYq5aTRHaVUskdT3I5u/pyznb5ODLumC8CP9KTPvRgBJzgba0Rktu6uqOm6UAJOOjjDzxspnk1WniPR0rHUPYqd17HYPExljfQpjJ6ojS/uag00ryL4WOdqYjTTnHQuljxFBNXmsjxfAolv0OyGcIE31KP7L+H8h6qoQxrt/dJv/jt+RnXsEuH7taIZT7kbSQ1ilaOhzrz5vG4BLwZhUVd/Mr5LQ7KprPF0IsVR12wqeGjAgC/IhGiBARUNMBvLE8OJ/CdO/Z+elnJyenp88vvaY6mc1O+XAu45px5ExfZSvs5i7Cu6G2Nm/zB0rUFm2Az7nG8+YiGMKf9GWMcFEG39FZ2zBDOziGKeiDUf2lgHyGA6IPRNqX4C8WayyZu2BffvfcBRKJtrSJuVI9bHJ7Amz6Qwlg7rMrM1CVWf1SijiciCAIB6voZB0HroZTH44Fbn1Dfe1krBvOP94zXZvJrpLvc6gXtyV1QRe2tZM6dfybyXl3/rpM1iMOrm1icrISV3mlipZ/TJ5GlmDO0rKkmdoCDP0YYOf1EiMJjx4detsRNwF/V6RsrlrvCKC9fuNU94nTkmCiOgkrtLXQMai4LsxjPw5XOqIrnqPhZNggaKirK23t3hIfKgjS/QqEbmcy6tNNnCNSzQZGrjcuN7pG//Ddr9CcOYQR0ngeClsnIvxaThxJ+WDrZGtYRLvd3jv+oCmqRyglBnwXYEkxXMWTJiRdYHE1tie/xlma1P1mdUp271FqKV6quRQ1miI8zb+DJxwND9R/FmojOt0kvQScf9DlN7aBH9+zWSE+7mXNDDjt9nlvqKEbJLogvsVdL5yjSA6M9N4/FwlgyJpRdfqjvDKwGh31qkSWrP7VF5Ezon64WnEFrRvMZA44+yJBPljx4vII5gai";
        String algorithm = "AEAD_AES_256_GCM";
        savePlatformCert(associatedData, nonce, cipherText, algorithm, "D:/ticket/platform_cert.pem");
    }

}
